package org.hongbo.springbootebsapi.service.responsibility.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import lombok.extern.slf4j.Slf4j;
import org.hongbo.springbootebsapi.jwt.Audience;
import org.hongbo.springbootebsapi.jwt.JwtTokenUtil;
import org.hongbo.springbootebsapi.entity.AuthUser;
import org.hongbo.springbootebsapi.service.login.ICurrentUser;
import org.hongbo.springbootebsapi.service.login.ILoginService;
import org.hongbo.springbootebsapi.service.responsibility.IResponService;
import org.hongbo.springbootebsapi.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.hongbo.springbootebsapi.entity.responsibility.UserFuncEntity;
import org.hongbo.springbootebsapi.util.DBConnection;
import org.hongbo.springbootebsapi.util.DBUtil;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

import static org.hongbo.springbootebsapi.util.ReflectUtil.reflect;

@Slf4j
@Service
@Transactional
public class ResponServiceImpl implements IResponService {
    @Autowired
    protected JdbcTemplate jdbcTemplate;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private DBConnection dbConnection;

    @Autowired
    private DBUtil dbUtil;

    @Autowired
    private ICurrentUser currentUser;

    @Autowired
    private ILoginService loginService;

    @Autowired
    private Audience audience;

    @Autowired
    JwtTokenUtil jwtTokenUtil;

    @Autowired
    HttpServletRequest request;


    /**
     * 参考：http://sunbin123.iteye.com/blog/1007556
     */
    @Override
    public void initResponsiblity(String userId,
                                   String respId,
                                   String respApplId){
//        log.info("当前的user_id "+ user_id+" resp_id "+resp_id+" resp_appl_id "+resp_appl_id);
//        log.info("正在执行 ResponServiceImpl");

        String initSql = "begin fnd_global.APPS_INITIALIZE("+userId+","+respId+","+respApplId+"); " +
                          "      MO_GLOBAL.init('S');" +
                          "end;";

        jdbcTemplate.execute(initSql);

    }

    @Override
    public void initResponsiblity(){

        String userId = currentUser.getCurrentUserId();
        String respId = currentUser.getCurrentRespId();
        String respApplId = currentUser.getCurrentRespApplId();
        //非空则初始化
        if(StringUtil.isNotEmpty(userId)&&StringUtil.isNotEmpty(respId)&&StringUtil.isNotEmpty(respApplId)){
//            String initSql = "begin fnd_global.APPS_INITIALIZE("+user_id+","+resp_id+","+resp_appl_id+"); end;";
//            jdbcTemplate.execute(initSql);
            log.info("带User信息，执行初始化");
            initResponsiblity(userId,respId,respApplId);
        }else if(StringUtil.isNotEmpty(userId)&&StringUtil.isEmpty(respId)&&StringUtil.isEmpty(respApplId)){
            log.info("带User信息但是不完整，执行用户初始化");
            initResponsiblity(userId, null, null);
        }
        else {
            log.info("不带User信息，不执行初始化");
        }

    }

    @Override
    public String getUserFuncStr(String userId){

        String userFuncStr = null;
//        return  userFuncStr;

//        HashOperations ops = redisTemplate.opsForHash();
//        String hashTab  = "UserFuncMap";
//
//        log.info("是否存在 "+ops.hasKey(hashTab,userId));
//        if(ops.hasKey(hashTab,userId)){
//            userFuncStr = (String)ops.get(hashTab,userId);
//            log.info(userFuncStr);
//
//        }else{
//            List<UserFuncEntity> menuList = new ArrayList<>();
//            menuList = getUserFuncEntity(userId);
//            //若出现引用类型，需要强制去掉引用，js中不能识别引用
//            userFuncStr = JSON.toJSONString(menuList,SerializerFeature.DisableCircularReferenceDetect );
//
//            ops.put(hashTab,userId,userFuncStr);
//        }

        List<UserFuncEntity> menuList = new ArrayList<>();
        menuList = getUserFuncEntity(userId);
        //若出现引用类型，需要强制去掉引用，js中不能识别引用
        userFuncStr = JSON.toJSONString(menuList,SerializerFeature.DisableCircularReferenceDetect,SerializerFeature.PrettyFormat );
        log.info("userFuncStr \n"+userFuncStr);
        return userFuncStr;


    }

    @Override
    public List<UserFuncEntity> getUserFuncEntity(String userId){


        //在职责层加入了CUX_18_ASSIGN_WEB_API配置文件的职责才会被显示
        String respSql = "SELECT furg.responsibility_id,\n" +
                "       furg.responsibility_application_id,\n" +
                "       frv.responsibility_name\n" +
                "  FROM fnd_user_resp_groups_all furg, fnd_responsibility_vl frv\n" +
                " WHERE furg.user_id = ? \n"+
                "   AND furg.responsibility_id = frv.responsibility_id" +
                "   AND SYSDATE BETWEEN furg.start_date AND nvl(furg.end_date, SYSDATE + 1)\n" +
                "   AND EXISTS\n" +
                " (SELECT 1\n" +
                "          FROM fnd_profile_option_values fpv, fnd_profile_options_vl fpo\n" +
                "         WHERE fpv.level_value = frv.responsibility_id\n" +
                "           AND fpv.level_id = 10003\n" +
                "           AND fpv.profile_option_id = fpo.profile_option_id\n" +
                "           AND fpo.profile_option_name = 'CUX_18_ASSIGN_WEB_API')";

        String respFuncSql = "SELECT res.responsibility_name,\n" +
                "       menu.menu_name,\n" +
                "       menu.user_menu_name,\n" +
                "       func.function_name,\n" +
                "       func.user_function_name,\n" +
                "       sub_menu.prompt,\n" +
                "       func.type\n" +
                "  FROM fnd_responsibility_vl res,\n" +
                "       fnd_menus_vl          menu,\n" +
                "       fnd_menu_entries_vl   sub_menu,\n" +
                "       fnd_form_functions_vl func\n" +
                " WHERE res.menu_id = sub_menu.menu_id\n" +
                "   AND menu.menu_id = sub_menu.menu_id\n" +
                "   AND sub_menu.function_id = func.function_id\n" +
                "   AND sub_menu.sub_menu_id IS NULL\n" +
                "   AND sub_menu.function_id IS NOT NULL\n" +
                "   AND sub_menu.prompt IS NOT NULL\n" +
                "   AND func.function_name NOT IN\n" +
                "       ('FNDCPSRSSSWA', 'FNDCPVIEWREQUEST', 'ICX_SSWA_USER_PREFERENCES')"+
                "   AND func.type = 'JSP'\n" +
                "   AND res.RESPONSIBILITY_ID = ? \n" +
                "UNION \n" +
                "SELECT res.responsibility_name,\n" +
                "       menu.menu_name,\n" +
                "       menu.user_menu_name,\n" +
                "       func.function_name,\n" +
                "       func.user_function_name,\n" +
                "       sub_menu1.prompt,\n" +
                "       func.type\n" +
                "  FROM fnd_responsibility_vl res,\n" +
                "       fnd_menus_vl          menu,\n" +
                "       fnd_menu_entries_vl   sub_menu,\n" +
                "       fnd_menu_entries_vl   sub_menu1,\n" +
                "       fnd_form_functions_vl func\n" +
                " WHERE res.menu_id = sub_menu.menu_id\n" +
                "   AND sub_menu.menu_id = menu.menu_id\n" +
                "   AND sub_menu.sub_menu_id = sub_menu1.menu_id\n" +
                "   AND sub_menu1.function_id = func.function_id\n" +
                "   AND sub_menu.sub_menu_id IS NOT NULL\n" +
                "   AND sub_menu.function_id IS NULL\n" +
                "   AND sub_menu1.prompt IS NOT NULL\n" +
                "   AND func.function_name NOT IN\n" +
                "       ('FNDCPSRSSSWA', 'FNDCPVIEWREQUEST', 'ICX_SSWA_USER_PREFERENCES')"+
                "   AND func.type = 'JSP'\n" +
                "   AND res.RESPONSIBILITY_ID = ?";


        //方法1，直接使用JdbcTemplate
//        List<UserFuncEntity> menuList = new ArrayList<>();
//        String respId = null;
//        String respApplId = null;
//        String respName = null;
//        String name = null;
//        List rows = jdbcTemplate.queryForList(respSql);
//        List rows = jdbcTemplate.queryForList(respSql,new Object[] {userId});
////        log.info("用户拥有的职责数量 "+ rows.size());
//
////        List<Map<String,Object>> rows =null;
////        try {
////            rows = DBUtil.executeQuery(dbConnection.getCon(), respSql);
////        }catch (SQLException e){
////            e.printStackTrace();
////        }
//        Iterator it = rows.iterator();
//        while(it.hasNext()) {
//            Map respMap = (Map) it.next();
//            respId = String.valueOf( respMap.get("responsibility_id".toUpperCase()));
//            respApplId = String.valueOf( respMap.get("responsibility_application_id".toUpperCase()));
//            respName = String.valueOf( respMap.get("responsibility_name".toUpperCase()));
//            name = respName;
//            if(respName.startsWith("B18")){
//                name = respName.substring(10);
//            }
//            UserFuncEntity userFuncEntity = new UserFuncEntity();
//            userFuncEntity.setRespId(respId);
//            userFuncEntity.setRespApplId(respApplId);
//            userFuncEntity.setName(name);
//
//            String respFuncListSql = getRespFuncListSql(respId);
//            List<UserFuncEntity> childList = new ArrayList<>();
////            List funcRows = jdbcTemplate.queryForList(respFuncListSql);
//            List funcRows = jdbcTemplate.queryForList(respFuncSql,new Object[]{respId, respId});
////            log.info("职责"+respName+"下拥有的功能数量"+funcRows.size());
////            List funcRows = null;
////            try {
////                funcRows = DBUtil.executeQuery(dbConnection.getCon(),respFuncListSql);
////            }catch (SQLException e){
////                e.printStackTrace();
////            }
//
//            Iterator funcIt = funcRows.iterator();
//            //判断职责下是否有可用的功能
//            int i=0;
//            while (funcIt.hasNext()){
//                Map funcMap = (Map) funcIt.next();
////                respId = String.valueOf(funcMap.get(""));
////                respApplId = String.valueOf(funcMap.get(""));
//                name = String.valueOf(funcMap.get("prompt"));
//                UserFuncEntity funcEntity = new UserFuncEntity();
//                funcEntity.setRespId(respId);
//                funcEntity.setRespApplId(respApplId);
//                funcEntity.setName(name);
//                if(i%2==0)
//                    funcEntity.setReqMapping("/test");
//                else
//                    funcEntity.setReqMapping("/echart");
//                childList.add(funcEntity);
//                i++;
//            }
//            if(i==0)
//                continue;
//
//            userFuncEntity.setChild(childList);
//
//            menuList.add(userFuncEntity);
//        }
//        return menuList;


        //另一种方法，通过反射的方式直接生成JavaBean
        List<UserFuncEntity> menuList = new ArrayList<>();
        List<Map<String, Object>> respList = jdbcTemplate.queryForList(respSql,new Object[]{ userId });
        for (Map<String, Object> jdbcMapResult : respList){
            UserFuncEntity userRespon =reflect(UserFuncEntity.class, jdbcMapResult);
            List<Map<String, Object>> responFuncMenu =jdbcTemplate.queryForList(respFuncSql,new Object[]{userRespon.getRespId(),userRespon.getRespId()});

            List<UserFuncEntity> respFuncList = new LinkedList<UserFuncEntity>();
            int i=0;
            for (Map<String, Object> respFuncListMap: responFuncMenu){
                UserFuncEntity func = reflect(UserFuncEntity.class, respFuncListMap);
                func.setRespId(userRespon.getRespId());
                func.setRespApplId(userRespon.getRespApplId());
                if(i%2==0) {
//                    func.setReqMapping("/test");
                    func.setReqMapping("/responsibility/userinfo");
                }
                else {
                    func.setReqMapping("/echart");
                }
                i++;
                respFuncList.add(func);
            }
            userRespon.setChild(respFuncList);
            //利用工具类反向生成bean
            menuList.add(userRespon);
        }
        return  menuList;

    }

    private static String getRespFuncListSql(String respId){
        String respFuncSql = "SELECT res.responsibility_name,\n" +
                "       menu.menu_name,\n" +
                "       menu.user_menu_name,\n" +
                "       func.function_name,\n" +
                "       func.user_function_name,\n" +
                "       sub_menu.prompt,\n" +
                "       func.type\n" +
                "  FROM fnd_responsibility_vl res,\n" +
                "       fnd_menus_vl          menu,\n" +
                "       fnd_menu_entries_vl   sub_menu,\n" +
                "       fnd_form_functions_vl func\n" +
                " WHERE res.menu_id = sub_menu.menu_id\n" +
                "   AND menu.menu_id = sub_menu.menu_id\n" +
                "   AND sub_menu.function_id = func.function_id\n" +
                "   AND sub_menu.sub_menu_id IS NULL\n" +
                "   AND sub_menu.function_id IS NOT NULL\n" +
                "   AND sub_menu.prompt IS NOT NULL\n" +
                "   AND func.function_name NOT IN\n" +
                "       ('FNDCPSRSSSWA', 'FNDCPVIEWREQUEST', 'ICX_SSWA_USER_PREFERENCES')"+
                "   AND func.type = 'JSP'\n" +
                "\t and res.RESPONSIBILITY_ID = "+respId+"\n" +
                "UNION \n" +
                "SELECT res.responsibility_name,\n" +
                "       menu.menu_name,\n" +
                "       menu.user_menu_name,\n" +
                "       func.function_name,\n" +
                "       func.user_function_name,\n" +
                "       sub_menu1.prompt,\n" +
                "       func.type\n" +
                "  FROM fnd_responsibility_vl res,\n" +
                "       fnd_menus_vl          menu,\n" +
                "       fnd_menu_entries_vl   sub_menu,\n" +
                "       fnd_menu_entries_vl   sub_menu1,\n" +
                "       fnd_form_functions_vl func\n" +
                " WHERE res.menu_id = sub_menu.menu_id\n" +
                "   AND sub_menu.menu_id = menu.menu_id\n" +
                "   AND sub_menu.sub_menu_id = sub_menu1.menu_id\n" +
                "   AND sub_menu1.function_id = func.function_id\n" +
                "   AND sub_menu.sub_menu_id IS NOT NULL\n" +
                "   AND sub_menu.function_id IS NULL\n" +
                "   AND sub_menu1.prompt IS NOT NULL\n" +
                "   AND func.function_name NOT IN\n" +
                "       ('FNDCPSRSSSWA', 'FNDCPVIEWREQUEST', 'ICX_SSWA_USER_PREFERENCES')"+
                "   AND func.type = 'JSP'\n" +
                "\t and res.RESPONSIBILITY_ID = "+respId;

        return  respFuncSql;

    }

    @Override
    public String getUserInfo(AuthUser user){
        try {
            Thread.sleep(60*10000);
        }catch (Exception e){
            e.printStackTrace();
        }
        Map modal = new LinkedHashMap();
        log.info("getUserInfo  userInfo  "+currentUser.getCurrentUserId()+" "+currentUser.getCurrentUserName());
        modal.put("userId",loginService.getLoginUserId());
        modal.put("userName",loginService.getLoginUserName());
        modal.put("employeeId",loginService.getEmployeeId());
        modal.put("respId",loginService.getCurrentRespId());
        modal.put("respApplId",loginService.getCurrentRespApplId());
        modal.put("respName",loginService.getRespName());
        modal.put("orgId",loginService.getOrgId());
        log.info("getUserInfo  "+JSON.toJSONString(modal));
        return JSON.toJSONString(modal);
    }

    @Override
    public String getLoginInfo(){
        Map modal = new LinkedHashMap();
        log.info("getUserInfo  userInfo  "+currentUser.getCurrentUserId()+" "+currentUser.getCurrentUserName());
        modal.put("userId",loginService.getLoginUserId());
        modal.put("userName",loginService.getLoginUserName());
        modal.put("employeeId",loginService.getEmployeeId());
        modal.put("respId",loginService.getCurrentRespId());
        modal.put("respApplId",loginService.getCurrentRespApplId());
        modal.put("respName",loginService.getRespName());
        modal.put("orgId",loginService.getOrgId());
        log.info("getUserInfo  "+JSON.toJSONString(modal));
        return JSON.toJSONString(modal);
    }

    @Override
    public String getRespSwitcherToken(String respId, String respApplId){


        AuthUser userDetails = currentUser.getCurrentUser();
        userDetails.setRespId(respId);
        userDetails.setRespApplId(respApplId);

        //授权
        //可以不在此处授权
//        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
//                userDetails, null, userDetails.getAuthorities());
//        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
//        SecurityContextHolder.getContext().setAuthentication(authentication);

        String tokenStr =audience.getTokenHead() +  jwtTokenUtil.generateToken(userDetails);


        return tokenStr;
    }

}
